from sqlalchemy.orm import Session
from models import Admin, Landmark, Route
from passlib.context import CryptContext
from typing import List, Optional
import json

# 密码加密上下文
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

def verify_password(plain_password, hashed_password):
    """验证密码"""
    return pwd_context.verify(plain_password, hashed_password)

def get_password_hash(password):
    """获取密码哈希值"""
    return pwd_context.hash(password)

# 管理员相关操作
def get_admin(db: Session, admin_id: int):
    return db.query(Admin).filter(Admin.id == admin_id).first()

def get_admin_by_username(db: Session, username: str):
    return db.query(Admin).filter(Admin.username == username).first()

def get_admin_by_email(db: Session, email: str):
    return db.query(Admin).filter(Admin.email == email).first()

def create_admin(db: Session, username: str, email: str, full_name: str, password: str):
    hashed_password = get_password_hash(password)
    db_admin = Admin(
        username=username,
        email=email,
        full_name=full_name,
        hashed_password=hashed_password
    )
    db.add(db_admin)
    db.commit()
    db.refresh(db_admin)
    return db_admin

def authenticate_admin(db: Session, username: str, password: str):
    admin = get_admin_by_username(db, username=username)
    if not admin:
        return False
    if not verify_password(password, admin.hashed_password):
        return False
    return admin

# 地标相关操作
def get_landmark(db: Session, landmark_id: int):
    return db.query(Landmark).filter(Landmark.id == landmark_id).first()

def get_landmarks(db: Session, skip: int = 0, limit: int = 100):
    return db.query(Landmark).offset(skip).limit(limit).all()

def create_landmark(db: Session, name: str, lat: float, lng: float, summary: str,
                   details: str, creator_id: int, media: List[str] = None,
                   time = None):
    media_json = json.dumps(media) if media else "[]"
    db_landmark = Landmark(
        name=name,
        lat=lat,
        lng=lng,
        summary=summary,
        details=details,
        creator_id=creator_id,
        media_json=media_json,
        time=time
    )
    db.add(db_landmark)
    db.commit()
    db.refresh(db_landmark)
    return db_landmark

def update_landmark(db: Session, landmark_id: int, name: str = None, lat: float = None,
                   lng: float = None, summary: str = None, details: str = None,
                   media: List[str] = None, time = None):
    db_landmark = get_landmark(db, landmark_id=landmark_id)
    if not db_landmark:
        return None

    if name is not None:
        db_landmark.name = name
    if lat is not None:
        db_landmark.lat = lat
    if lng is not None:
        db_landmark.lng = lng
    if summary is not None:
        db_landmark.summary = summary
    if details is not None:
        db_landmark.details = details
    if media is not None:
        db_landmark.media_json = json.dumps(media)
    if time is not None:
        db_landmark.time = time

    db.commit()
    db.refresh(db_landmark)
    return db_landmark

def delete_landmark(db: Session, landmark_id: int):
    db_landmark = get_landmark(db, landmark_id=landmark_id)
    if not db_landmark:
        return None

    db.delete(db_landmark)
    db.commit()
    return True

# 路径相关操作
def get_route(db: Session, route_id: int):
    return db.query(Route).filter(Route.id == route_id).first()

def get_routes(db: Session, skip: int = 0, limit: int = 100):
    return db.query(Route).offset(skip).limit(limit).all()

def create_route(db: Session, name: str, creator_id: int, landmark_ids: List[int] = None):
    db_route = Route(
        name=name,
        creator_id=creator_id
    )

    if landmark_ids:
        landmarks = db.query(Landmark).filter(Landmark.id.in_(landmark_ids)).all()
        db_route.landmarks = landmarks

    db.add(db_route)
    db.commit()
    db.refresh(db_route)
    return db_route

def update_route(db: Session, route_id: int, name: str = None, landmark_ids: List[int] = None):
    db_route = get_route(db, route_id=route_id)
    if not db_route:
        return None

    if name is not None:
        db_route.name = name

    if landmark_ids is not None:
        landmarks = db.query(Landmark).filter(Landmark.id.in_(landmark_ids)).all()
        db_route.landmarks = landmarks

    db.commit()
    db.refresh(db_route)
    return db_route

def delete_route(db: Session, route_id: int):
    db_route = get_route(db, route_id=route_id)
    if not db_route:
        return None

    db.delete(db_route)
    db.commit()
    return True

def get_route_details(db: Session, route_id: int):
    route = get_route(db, route_id=route_id)
    if not route:
        return None

    return {
        "id": route.id,
        "name": route.name,
        "landmarks": route.landmarks,
        "creator_id": route.creator_id,
        "creator": route.creator,
        "created_at": route.created_at,
        "updated_at": route.updated_at
    }
